package com.gzx.plugin.tjzy.modular.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fhs.trans.service.impl.DictionaryTransService;
import com.gzx.plugin.tjzy.core.entity.CustomVo;
import com.gzx.plugin.tjzy.modular.product.entity.GzxProduct;
import com.gzx.plugin.tjzy.modular.product.entity.bo.GzxProductBo;
import com.gzx.plugin.tjzy.modular.product.entity.bo.GzxProductIdBo;
import com.gzx.plugin.tjzy.modular.product.entity.bo.GzxProductQueryBo;
import com.gzx.plugin.tjzy.modular.product.entity.vo.GzxProductVo;
import com.gzx.plugin.tjzy.modular.product.mapper.GzxProductMapper;
import com.gzx.plugin.tjzy.modular.product.service.GzxProductListService;
import com.gzx.plugin.tjzy.modular.product.service.GzxProductService;
import io.micrometer.common.util.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import vip.xiaonuo.common.consts.GzxDictConstant;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.tenant.TenantContext;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 委托公司产品Service业务层处理
 *
 * @author LionLi
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class GzxProductServiceImpl implements GzxProductService, InitializingBean {

    private final GzxProductMapper baseMapper;

    private final GzxProductListService productListService;

    private final DictionaryTransService dictionaryTransService;

    /**
     * 分页查询委托公司产品列表
     *
     * @param productQueryBo 查询条件
     * @return 委托公司产品分页列表
     */
    @Override
    @DS("tjzy")
    public Page<GzxProductVo> pageList(GzxProductQueryBo productQueryBo) {
        LambdaQueryWrapper<GzxProduct> lqw = Wrappers.lambdaQuery();
        //公司编码
        lqw.eq(productQueryBo.getCompanyCode() != null, GzxProduct::getCompanyCode, productQueryBo.getCompanyCode());
        //产品编码
        lqw.eq(StringUtils.isNotBlank(productQueryBo.getProductCode()), GzxProduct::getProductCode, productQueryBo.getProductCode());
        //产品名称
        lqw.like(StringUtils.isNotBlank(productQueryBo.getProductName()), GzxProduct::getProductName, productQueryBo.getProductName());
        //产品描述
        lqw.eq(StringUtils.isNotBlank(productQueryBo.getProductDescription()), GzxProduct::getProductDescription, productQueryBo.getProductDescription());
        lqw.orderByDesc(GzxProduct::getProductName);
        return baseMapper.selectVoPage(new Page<>(productQueryBo.getCurrent(), productQueryBo.getSize()), lqw);
    }

    /**
     * 查询委托公司产品
     *
     * @param id 主键
     * @return 委托公司产品
     */
    @Override
    @DS("tjzy")
    public GzxProductVo queryById(Long id) {
        return BeanUtil.toBean(baseMapper.selectById(id), GzxProductVo.class);
    }

    @Override
    @DS("tjzy")
    public List<CustomVo> listAll(boolean flag, String val) {
        LambdaQueryWrapper<GzxProduct> lqw = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(val)) {
            if (flag) {
                lqw.like(GzxProduct::getProductName, val).or().like(GzxProduct::getProductCode, val);
            } else {
                lqw.like(GzxProduct::getCompanyCode, val);
            }
        }
        return convertList(baseMapper.selectVoList(lqw));
    }

    /**
     * 新增委托公司产品
     *
     * @param bo 委托公司产品
     */
    @Override
    @DS("tjzy")
    public void insertByBo(GzxProductBo bo) {
        GzxProduct product = BeanUtil.toBean(bo, GzxProduct.class);
        validEntityBeforeSave(product);
        baseMapper.insert(product);
        refreshTransCache();
    }

    /**
     * 修改委托公司产品
     *
     * @param bo 委托公司产品
     */
    @Override
    @DS("tjzy")
    public void updateByBo(GzxProductBo bo) {
        GzxProduct product = BeanUtil.toBean(bo, GzxProduct.class);
        validEntityBeforeSave(product);
        baseMapper.updateById(product);
        refreshTransCache();
    }

    /**
     * 校验并批量删除委托公司产品信息
     */
    @Override
    @DS("tjzy")
    public void deleteWithValidByIds(GzxProductIdBo productIdBo) {
        baseMapper.deleteBatchIds(productIdBo.getProductIdList());
        refreshTransCache();
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(GzxProduct product) {
        //校验唯一产品编码是否存在
        LambdaQueryWrapper<GzxProduct> lqw = Wrappers.lambdaQuery();
        lqw.eq(GzxProduct::getProductCode, product.getProductCode());
        lqw.ne(product.getId() != null, GzxProduct::getId, product.getId());
        if (CollectionUtil.isNotEmpty(baseMapper.selectList(lqw))) {
            throw new CommonException(product.getProductCode() + "：产品编码已存在");
        }
    }

    private List<CustomVo> convertList(List<GzxProductVo> productVoList) {
        List<CustomVo> customVoList = new ArrayList<>();
        for (GzxProductVo productVo : productVoList) {
            CustomVo customVo = new CustomVo();
            customVo.setId(Long.valueOf(productVo.getId()));//修改
            customVo.setValue(productVo.getProductCode());
            customVo.setLabel(productVo.getProductName());
            customVoList.add(customVo);
        }
        return customVoList;
    }

    @Override
    public void afterPropertiesSet() {
        refreshTransCache();
    }

    private void refreshTransCache() {
        CompletableFuture.supplyAsync(() -> {
            // 使用redis能解决共享问题，但是性能没有直接取缓存的好。
            dictionaryTransService.makeUseRedis();
            try {
                TenantContext.disableTenantFilter();
                List<GzxProduct> projectList = productListService.getList();
                dictionaryTransService.refreshCache(GzxDictConstant.PRODUCT, projectList.stream().collect(Collectors.toMap(GzxProduct::getProductCode, GzxProduct::getProductName)));
            } finally {
                TenantContext.enableTenantFilter();
                TenantContext.clear();
            }
            return null;
        }).exceptionally(ex -> {
            log.error("刷新产品缓存发生异常:", ex);
            return null;
        });
    }
}
